
// -*-c++-*-
//-------------------------------------------------------------------------
//   Copyright 2002-2021 National Technology & Engineering Solutions of
//   Sandia, LLC (NTESS).  Under the terms of Contract DE-NA0003525 with
//   NTESS, the U.S. Government retains certain rights in this software.
//
//   This file is part of the Xyce(TM) Parallel Electrical Simulator.
//
//   Xyce(TM) is free software: you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   Xyce(TM) is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with Xyce(TM).
//   If not, see <http://www.gnu.org/licenses/>.
//-------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//
// Purpose        :
//
// Special Notes  : Generated from verilog file mvsg_cmc_1.1.0.va with ADMS
//                  interface for Xyce 7.3.0
//                  DO NOT EDIT THIS FILE DIRECTLY!  It may be overwritten!
//
// Creator        : admsXml-2.3.6
//
// Creation Date  : Sun, 18 Apr 2021 10:09:00
//
//-----------------------------------------------------------------------------
#ifndef Xyce_N_DEV_ADMSmvsg_cmc_h
#define Xyce_N_DEV_ADMSmvsg_cmc_h


#include <N_DEV_Configuration.h>
#include <N_DEV_Const.h>
#include <N_DEV_DeviceBlock.h>
#include <N_DEV_DeviceInstance.h>
#include <N_DEV_DeviceModel.h>
#include <N_DEV_MOSFET1.h>


// Xyce_config.h contains a VERSION macro from autoconf, and some
// Verilog-A models like to define a variable of that name.  This can be
// a serious problem, and we don't need the VERSION macro.  Get rid of it.
// This must happen *after* all the includes of Xyce headers, each of which
// includes Xyce_config.h.  The implementation file must do this all again
// because it includes more Xyce headers *after* including this one.
#ifdef VERSION
#undef VERSION
#endif

namespace Xyce {
namespace Device {
namespace ADMSmvsg_cmc {

class Model;
class Instance;
class InstanceSensitivity;

#ifdef Xyce_ADMS_SENSITIVITIES
//-----------------------------------------------------------------------------
// Class         : InstanceSensitivity
//
// Purpose       : This class is a functor for sensitivity
//
// Special Notes :
// Creator       :
// Creation Date :
//-----------------------------------------------------------------------------
class InstanceSensitivity : public baseSensitivity
{
public:
InstanceSensitivity() :
baseSensitivity() {};

virtual ~InstanceSensitivity() {};

virtual void operator()(
const ParameterBase &entity,
const std::string &param,
std::vector<double> & dfdp,
std::vector<double> & dqdp,
std::vector<double> & dbdp,
std::vector<int> & Findices,
std::vector<int> & Qindices,
std::vector<int> & Bindices
) const ;
};

static InstanceSensitivity instSens;


//-----------------------------------------------------------------------------
// Class         : ModelSensitivity
//
// Purpose       : This class is a functor for sensitivity
//
// Special Notes :
// Creator       :
// Creation Date :
//-----------------------------------------------------------------------------
class ModelSensitivity : public baseSensitivity
{
public:
ModelSensitivity() :
baseSensitivity() {};

virtual ~ModelSensitivity() {};

virtual void operator()(
const ParameterBase &entity,
const std::string &param,
std::vector<double> & dfdp,
std::vector<double> & dqdp,
std::vector<double> & dbdp,
std::vector<int> & Findices,
std::vector<int> & Qindices,
std::vector<int> & Bindices
) const ;
};

static ModelSensitivity modSens;
#endif // Xyce_ADMS_SENSITIVITIES

// general purpose free functions
// thermal voltage at kelvin temperature temp)
template <typename T> static inline T adms_vt(const T temp) {return(CONSTKoverQ*temp);};

// Figure out how to template this shiznit!
//-----------------------------------------------------------------------------


template<typename Tin>
static Tin adms_ternary_op(const bool cond, const Tin &ifTrue, const Tin &ifFalse)
{
if (cond)
return ifTrue;
else
return ifFalse;
}

template<typename Tin>
static Tin adms_ternary_op(const bool cond, const Tin &ifTrue, const double &ifFalse)
{
if (cond)
return ifTrue;
else
return Tin(ifFalse);
}

template<typename Tin>
static Tin adms_ternary_op(const bool cond, const double &ifTrue, const Tin &ifFalse)
{
if (cond)
return Tin(ifTrue);
else
return ifFalse;
}




#ifdef Xyce_ADMS_SENSITIVITIES
//-----------------------------------------------------------------------------
// "structs" to hold instance and model param/variable copies
//-----------------------------------------------------------------------------
class instanceSensStruct
{
public:
// instance parameters
// reals
double instancePar_w;
double d_instancePar_w_dX;
bool instancePar_given_w;
double instancePar_l;
double d_instancePar_l_dX;
bool instancePar_given_l;
double instancePar_dtemp;
double d_instancePar_dtemp_dX;
bool instancePar_given_dtemp;
// non-reals(including hidden)
int instancePar_ngf;
bool instancePar_given_ngf;
// instance variables
// reals
double instanceVar_rcs_w;
double d_instanceVar_rcs_w_dX;
double instanceVar_rcd_w;
double d_instanceVar_rcd_w_dX;
double instanceVar_rg;
double d_instanceVar_rg_dX;
};

class modelSensStruct
{
public:
// model parameters
// reals
double modelPar_version;
double d_modelPar_version_dX;
bool modelPar_given_version;
double modelPar_tnom;
double d_modelPar_tnom_dX;
bool modelPar_given_tnom;
double modelPar_cg;
double d_modelPar_cg_dX;
bool modelPar_given_cg;
double modelPar_cofsm;
double d_modelPar_cofsm_dX;
bool modelPar_given_cofsm;
double modelPar_cofdm;
double d_modelPar_cofdm_dX;
bool modelPar_given_cofdm;
double modelPar_cofdsm;
double d_modelPar_cofdsm_dX;
bool modelPar_given_cofdsm;
double modelPar_cofdsubm;
double d_modelPar_cofdsubm_dX;
bool modelPar_given_cofdsubm;
double modelPar_cofssubm;
double d_modelPar_cofssubm_dX;
bool modelPar_given_cofssubm;
double modelPar_cofgsubm;
double d_modelPar_cofgsubm_dX;
bool modelPar_given_cofgsubm;
double modelPar_rsh;
double d_modelPar_rsh_dX;
bool modelPar_given_rsh;
double modelPar_rcs;
double d_modelPar_rcs_dX;
bool modelPar_given_rcs;
double modelPar_rcd;
double d_modelPar_rcd_dX;
bool modelPar_given_rcd;
double modelPar_vx0;
double d_modelPar_vx0_dX;
bool modelPar_given_vx0;
double modelPar_mu0;
double d_modelPar_mu0_dX;
bool modelPar_given_mu0;
double modelPar_beta;
double d_modelPar_beta_dX;
bool modelPar_given_beta;
double modelPar_vto;
double d_modelPar_vto_dX;
bool modelPar_given_vto;
double modelPar_ss;
double d_modelPar_ss_dX;
bool modelPar_given_ss;
double modelPar_delta1;
double d_modelPar_delta1_dX;
bool modelPar_given_delta1;
double modelPar_delta2;
double d_modelPar_delta2_dX;
bool modelPar_given_delta2;
double modelPar_dibsat;
double d_modelPar_dibsat_dX;
bool modelPar_given_dibsat;
double modelPar_nd;
double d_modelPar_nd_dX;
bool modelPar_given_nd;
double modelPar_alpha;
double d_modelPar_alpha_dX;
bool modelPar_given_alpha;
double modelPar_lambda;
double d_modelPar_lambda_dX;
bool modelPar_given_lambda;
double modelPar_vtheta;
double d_modelPar_vtheta_dX;
bool modelPar_given_vtheta;
double modelPar_mtheta;
double d_modelPar_mtheta_dX;
bool modelPar_given_mtheta;
double modelPar_vzeta;
double d_modelPar_vzeta_dX;
bool modelPar_given_vzeta;
double modelPar_vtzeta;
double d_modelPar_vtzeta_dX;
bool modelPar_given_vtzeta;
double modelPar_epsilon;
double d_modelPar_epsilon_dX;
bool modelPar_given_epsilon;
double modelPar_rct1;
double d_modelPar_rct1_dX;
bool modelPar_given_rct1;
double modelPar_rct2;
double d_modelPar_rct2_dX;
bool modelPar_given_rct2;
double modelPar_lgs;
double d_modelPar_lgs_dX;
bool modelPar_given_lgs;
double modelPar_vtors;
double d_modelPar_vtors_dX;
bool modelPar_given_vtors;
double modelPar_cgrs;
double d_modelPar_cgrs_dX;
bool modelPar_given_cgrs;
double modelPar_vx0rs;
double d_modelPar_vx0rs_dX;
bool modelPar_given_vx0rs;
double modelPar_mu0rs;
double d_modelPar_mu0rs_dX;
bool modelPar_given_mu0rs;
double modelPar_betars;
double d_modelPar_betars_dX;
bool modelPar_given_betars;
double modelPar_delta1rs;
double d_modelPar_delta1rs_dX;
bool modelPar_given_delta1rs;
double modelPar_srs;
double d_modelPar_srs_dX;
bool modelPar_given_srs;
double modelPar_ndrs;
double d_modelPar_ndrs_dX;
bool modelPar_given_ndrs;
double modelPar_vthetars;
double d_modelPar_vthetars_dX;
bool modelPar_given_vthetars;
double modelPar_mthetars;
double d_modelPar_mthetars_dX;
bool modelPar_given_mthetars;
double modelPar_alphars;
double d_modelPar_alphars_dX;
bool modelPar_given_alphars;
double modelPar_lgd;
double d_modelPar_lgd_dX;
bool modelPar_given_lgd;
double modelPar_vtord;
double d_modelPar_vtord_dX;
bool modelPar_given_vtord;
double modelPar_cgrd;
double d_modelPar_cgrd_dX;
bool modelPar_given_cgrd;
double modelPar_vx0rd;
double d_modelPar_vx0rd_dX;
bool modelPar_given_vx0rd;
double modelPar_mu0rd;
double d_modelPar_mu0rd_dX;
bool modelPar_given_mu0rd;
double modelPar_betard;
double d_modelPar_betard_dX;
bool modelPar_given_betard;
double modelPar_delta1rd;
double d_modelPar_delta1rd_dX;
bool modelPar_given_delta1rd;
double modelPar_srd;
double d_modelPar_srd_dX;
bool modelPar_given_srd;
double modelPar_ndrd;
double d_modelPar_ndrd_dX;
bool modelPar_given_ndrd;
double modelPar_vthetard;
double d_modelPar_vthetard_dX;
bool modelPar_given_vthetard;
double modelPar_mthetard;
double d_modelPar_mthetard_dX;
bool modelPar_given_mthetard;
double modelPar_alphard;
double d_modelPar_alphard_dX;
bool modelPar_given_alphard;
double modelPar_lgfp1;
double d_modelPar_lgfp1_dX;
bool modelPar_given_lgfp1;
double modelPar_vtofp1;
double d_modelPar_vtofp1_dX;
bool modelPar_given_vtofp1;
double modelPar_cgfp1;
double d_modelPar_cgfp1_dX;
bool modelPar_given_cgfp1;
double modelPar_cfp1s;
double d_modelPar_cfp1s_dX;
bool modelPar_given_cfp1s;
double modelPar_ccfp1;
double d_modelPar_ccfp1_dX;
bool modelPar_given_ccfp1;
double modelPar_cbfp1;
double d_modelPar_cbfp1_dX;
bool modelPar_given_cbfp1;
double modelPar_vx0fp1;
double d_modelPar_vx0fp1_dX;
bool modelPar_given_vx0fp1;
double modelPar_mu0fp1;
double d_modelPar_mu0fp1_dX;
bool modelPar_given_mu0fp1;
double modelPar_betafp1;
double d_modelPar_betafp1_dX;
bool modelPar_given_betafp1;
double modelPar_delta1fp1;
double d_modelPar_delta1fp1_dX;
bool modelPar_given_delta1fp1;
double modelPar_sfp1;
double d_modelPar_sfp1_dX;
bool modelPar_given_sfp1;
double modelPar_ndfp1;
double d_modelPar_ndfp1_dX;
bool modelPar_given_ndfp1;
double modelPar_vthetafp1;
double d_modelPar_vthetafp1_dX;
bool modelPar_given_vthetafp1;
double modelPar_mthetafp1;
double d_modelPar_mthetafp1_dX;
bool modelPar_given_mthetafp1;
double modelPar_alphafp1;
double d_modelPar_alphafp1_dX;
bool modelPar_given_alphafp1;
double modelPar_lgfp2;
double d_modelPar_lgfp2_dX;
bool modelPar_given_lgfp2;
double modelPar_vtofp2;
double d_modelPar_vtofp2_dX;
bool modelPar_given_vtofp2;
double modelPar_cgfp2;
double d_modelPar_cgfp2_dX;
bool modelPar_given_cgfp2;
double modelPar_cfp2s;
double d_modelPar_cfp2s_dX;
bool modelPar_given_cfp2s;
double modelPar_ccfp2;
double d_modelPar_ccfp2_dX;
bool modelPar_given_ccfp2;
double modelPar_cbfp2;
double d_modelPar_cbfp2_dX;
bool modelPar_given_cbfp2;
double modelPar_vx0fp2;
double d_modelPar_vx0fp2_dX;
bool modelPar_given_vx0fp2;
double modelPar_mu0fp2;
double d_modelPar_mu0fp2_dX;
bool modelPar_given_mu0fp2;
double modelPar_betafp2;
double d_modelPar_betafp2_dX;
bool modelPar_given_betafp2;
double modelPar_delta1fp2;
double d_modelPar_delta1fp2_dX;
bool modelPar_given_delta1fp2;
double modelPar_sfp2;
double d_modelPar_sfp2_dX;
bool modelPar_given_sfp2;
double modelPar_ndfp2;
double d_modelPar_ndfp2_dX;
bool modelPar_given_ndfp2;
double modelPar_vthetafp2;
double d_modelPar_vthetafp2_dX;
bool modelPar_given_vthetafp2;
double modelPar_mthetafp2;
double d_modelPar_mthetafp2_dX;
bool modelPar_given_mthetafp2;
double modelPar_alphafp2;
double d_modelPar_alphafp2_dX;
bool modelPar_given_alphafp2;
double modelPar_lgfp3;
double d_modelPar_lgfp3_dX;
bool modelPar_given_lgfp3;
double modelPar_vtofp3;
double d_modelPar_vtofp3_dX;
bool modelPar_given_vtofp3;
double modelPar_cgfp3;
double d_modelPar_cgfp3_dX;
bool modelPar_given_cgfp3;
double modelPar_cfp3s;
double d_modelPar_cfp3s_dX;
bool modelPar_given_cfp3s;
double modelPar_ccfp3;
double d_modelPar_ccfp3_dX;
bool modelPar_given_ccfp3;
double modelPar_cbfp3;
double d_modelPar_cbfp3_dX;
bool modelPar_given_cbfp3;
double modelPar_vx0fp3;
double d_modelPar_vx0fp3_dX;
bool modelPar_given_vx0fp3;
double modelPar_mu0fp3;
double d_modelPar_mu0fp3_dX;
bool modelPar_given_mu0fp3;
double modelPar_betafp3;
double d_modelPar_betafp3_dX;
bool modelPar_given_betafp3;
double modelPar_delta1fp3;
double d_modelPar_delta1fp3_dX;
bool modelPar_given_delta1fp3;
double modelPar_sfp3;
double d_modelPar_sfp3_dX;
bool modelPar_given_sfp3;
double modelPar_ndfp3;
double d_modelPar_ndfp3_dX;
bool modelPar_given_ndfp3;
double modelPar_vthetafp3;
double d_modelPar_vthetafp3_dX;
bool modelPar_given_vthetafp3;
double modelPar_mthetafp3;
double d_modelPar_mthetafp3_dX;
bool modelPar_given_mthetafp3;
double modelPar_alphafp3;
double d_modelPar_alphafp3_dX;
bool modelPar_given_alphafp3;
double modelPar_lgfp4;
double d_modelPar_lgfp4_dX;
bool modelPar_given_lgfp4;
double modelPar_vtofp4;
double d_modelPar_vtofp4_dX;
bool modelPar_given_vtofp4;
double modelPar_cgfp4;
double d_modelPar_cgfp4_dX;
bool modelPar_given_cgfp4;
double modelPar_cfp4s;
double d_modelPar_cfp4s_dX;
bool modelPar_given_cfp4s;
double modelPar_ccfp4;
double d_modelPar_ccfp4_dX;
bool modelPar_given_ccfp4;
double modelPar_cbfp4;
double d_modelPar_cbfp4_dX;
bool modelPar_given_cbfp4;
double modelPar_vx0fp4;
double d_modelPar_vx0fp4_dX;
bool modelPar_given_vx0fp4;
double modelPar_mu0fp4;
double d_modelPar_mu0fp4_dX;
bool modelPar_given_mu0fp4;
double modelPar_betafp4;
double d_modelPar_betafp4_dX;
bool modelPar_given_betafp4;
double modelPar_delta1fp4;
double d_modelPar_delta1fp4_dX;
bool modelPar_given_delta1fp4;
double modelPar_sfp4;
double d_modelPar_sfp4_dX;
bool modelPar_given_sfp4;
double modelPar_ndfp4;
double d_modelPar_ndfp4_dX;
bool modelPar_given_ndfp4;
double modelPar_vthetafp4;
double d_modelPar_vthetafp4_dX;
bool modelPar_given_vthetafp4;
double modelPar_mthetafp4;
double d_modelPar_mthetafp4_dX;
bool modelPar_given_mthetafp4;
double modelPar_alphafp4;
double d_modelPar_alphafp4_dX;
bool modelPar_given_alphafp4;
double modelPar_rgsp;
double d_modelPar_rgsp_dX;
bool modelPar_given_rgsp;
double modelPar_vjg;
double d_modelPar_vjg_dX;
bool modelPar_given_vjg;
double modelPar_pg_param1;
double d_modelPar_pg_param1_dX;
bool modelPar_given_pg_param1;
double modelPar_pg_params;
double d_modelPar_pg_params_dX;
bool modelPar_given_pg_params;
double modelPar_ijs;
double d_modelPar_ijs_dX;
bool modelPar_given_ijs;
double modelPar_vgsats;
double d_modelPar_vgsats_dX;
bool modelPar_given_vgsats;
double modelPar_fracs;
double d_modelPar_fracs_dX;
bool modelPar_given_fracs;
double modelPar_alphags;
double d_modelPar_alphags_dX;
bool modelPar_given_alphags;
double modelPar_pg_paramd;
double d_modelPar_pg_paramd_dX;
bool modelPar_given_pg_paramd;
double modelPar_ijd;
double d_modelPar_ijd_dX;
bool modelPar_given_ijd;
double modelPar_vgsatd;
double d_modelPar_vgsatd_dX;
bool modelPar_given_vgsatd;
double modelPar_fracd;
double d_modelPar_fracd_dX;
bool modelPar_given_fracd;
double modelPar_alphagd;
double d_modelPar_alphagd_dX;
bool modelPar_given_alphagd;
double modelPar_pgsrecs;
double d_modelPar_pgsrecs_dX;
bool modelPar_given_pgsrecs;
double modelPar_irecs;
double d_modelPar_irecs_dX;
bool modelPar_given_irecs;
double modelPar_vgsatqs;
double d_modelPar_vgsatqs_dX;
bool modelPar_given_vgsatqs;
double modelPar_vbdgs;
double d_modelPar_vbdgs_dX;
bool modelPar_given_vbdgs;
double modelPar_pbdgs;
double d_modelPar_pbdgs_dX;
bool modelPar_given_pbdgs;
double modelPar_betarecs;
double d_modelPar_betarecs_dX;
bool modelPar_given_betarecs;
double modelPar_kbdgates;
double d_modelPar_kbdgates_dX;
bool modelPar_given_kbdgates;
double modelPar_pgsrecd;
double d_modelPar_pgsrecd_dX;
bool modelPar_given_pgsrecd;
double modelPar_irecd;
double d_modelPar_irecd_dX;
bool modelPar_given_irecd;
double modelPar_vgsatqd;
double d_modelPar_vgsatqd_dX;
bool modelPar_given_vgsatqd;
double modelPar_vbdgd;
double d_modelPar_vbdgd_dX;
bool modelPar_given_vbdgd;
double modelPar_pbdgd;
double d_modelPar_pbdgd_dX;
bool modelPar_given_pbdgd;
double modelPar_betarecd;
double d_modelPar_betarecd_dX;
bool modelPar_given_betarecd;
double modelPar_kbdgated;
double d_modelPar_kbdgated_dX;
bool modelPar_given_kbdgated;
double modelPar_rth;
double d_modelPar_rth_dX;
bool modelPar_given_rth;
double modelPar_cth;
double d_modelPar_cth_dX;
bool modelPar_given_cth;
double modelPar_taugmrf;
double d_modelPar_taugmrf_dX;
bool modelPar_given_taugmrf;
double modelPar_ctrap;
double d_modelPar_ctrap_dX;
bool modelPar_given_ctrap;
double modelPar_vttrap;
double d_modelPar_vttrap_dX;
bool modelPar_given_vttrap;
double modelPar_taut;
double d_modelPar_taut_dX;
bool modelPar_given_taut;
double modelPar_alphat1;
double d_modelPar_alphat1_dX;
bool modelPar_given_alphat1;
double modelPar_alphat2;
double d_modelPar_alphat2_dX;
bool modelPar_given_alphat2;
double modelPar_tempt;
double d_modelPar_tempt_dX;
bool modelPar_given_tempt;
double modelPar_shs;
double d_modelPar_shs_dX;
bool modelPar_given_shs;
double modelPar_shd;
double d_modelPar_shd_dX;
bool modelPar_given_shd;
double modelPar_kf;
double d_modelPar_kf_dX;
bool modelPar_given_kf;
double modelPar_af;
double d_modelPar_af_dX;
bool modelPar_given_af;
double modelPar_ffe;
double d_modelPar_ffe_dX;
bool modelPar_given_ffe;
double modelPar_minr;
double d_modelPar_minr_dX;
bool modelPar_given_minr;
double modelPar_minl;
double d_modelPar_minl_dX;
bool modelPar_given_minl;
double modelPar_minc;
double d_modelPar_minc_dX;
bool modelPar_given_minc;
double modelPar_LMIN;
double d_modelPar_LMIN_dX;
bool modelPar_given_LMIN;
double modelPar_WMIN;
double d_modelPar_WMIN_dX;
bool modelPar_given_WMIN;
double modelPar_LMAX;
double d_modelPar_LMAX_dX;
bool modelPar_given_LMAX;
double modelPar_WMAX;
double d_modelPar_WMAX_dX;
bool modelPar_given_WMAX;
// non-reals (including hidden)
int modelPar_type;
bool modelPar_given_type;
int modelPar_flagres;
bool modelPar_given_flagres;
int modelPar_flagfp1;
bool modelPar_given_flagfp1;
int modelPar_flagfp1s;
bool modelPar_given_flagfp1s;
int modelPar_flagfp2;
bool modelPar_given_flagfp2;
int modelPar_flagfp2s;
bool modelPar_given_flagfp2s;
int modelPar_flagfp3;
bool modelPar_given_flagfp3;
int modelPar_flagfp3s;
bool modelPar_given_flagfp3s;
int modelPar_flagfp4;
bool modelPar_given_flagfp4;
int modelPar_flagfp4s;
bool modelPar_given_flagfp4s;
int modelPar_igmod;
bool modelPar_given_igmod;
int modelPar_gmdisp;
bool modelPar_given_gmdisp;
int modelPar_trapselect;
bool modelPar_given_trapselect;
int modelPar_noisemod;
bool modelPar_given_noisemod;
};



//-----------------------------------------------------------------------------
// Free functions used by sensitivity
//
//-----------------------------------------------------------------------------
void evaluateModelEquations(
std::vector <double> & probeVars,
// probe constants
const int admsProbeID_V_si_GND,
const int admsProbeID_V_b_GND,
const int admsProbeID_V_di_GND,
const int admsProbeID_V_gi_GND,
const int admsProbeID_V_drc_d,
const int admsProbeID_V_gi_b,
const int admsProbeID_V_s_b,
const int admsProbeID_V_d_b,
const int admsProbeID_V_d_s,
const int admsProbeID_V_gi_d,
const int admsProbeID_V_gi_s,
const int admsProbeID_V_g_gi,
const int admsProbeID_V_d_drc,
const int admsProbeID_V_xt1_GND,
const int admsProbeID_V_xt2_GND,
const int admsProbeID_V_s_fp4,
const int admsProbeID_V_gi_fp4,
const int admsProbeID_V_b_fp3,
const int admsProbeID_V_fp4_fp3,
const int admsProbeID_V_s_fp3,
const int admsProbeID_V_gi_fp3,
const int admsProbeID_V_b_fp2,
const int admsProbeID_V_fp3_fp2,
const int admsProbeID_V_s_fp2,
const int admsProbeID_V_gi_fp2,
const int admsProbeID_V_b_fp1,
const int admsProbeID_V_fp2_fp1,
const int admsProbeID_V_s_fp1,
const int admsProbeID_V_gi_fp1,
const int admsProbeID_V_b_di,
const int admsProbeID_V_fp1_di,
const int admsProbeID_V_s_di,
const int admsProbeID_V_gi_di,
const int admsProbeID_V_drc_fp4,
const int admsProbeID_V_fp4_s,
const int admsProbeID_V_fp4_d,
const int admsProbeID_V_tr_GND,
const int admsProbeID_V_tr1_tr,
const int admsProbeID_V_d_g,
const int admsProbeID_V_si_src,
const int admsProbeID_V_src_s,
const int admsProbeID_V_src_d,
const int admsProbeID_V_gi_si,
const int admsProbeID_V_di_si,
const int admsProbeID_Temp_dt_GND,
// node constants
const int admsNodeID_d,
const int admsNodeID_g,
const int admsNodeID_s,
const int admsNodeID_b,
const int admsNodeID_di,
const int admsNodeID_gi,
const int admsNodeID_si,
const int admsNodeID_fp1,
const int admsNodeID_fp2,
const int admsNodeID_fp3,
const int admsNodeID_fp4,
const int admsNodeID_drc,
const int admsNodeID_src,
const int admsNodeID_tr,
const int admsNodeID_tr1,
const int admsNodeID_xt1,
const int admsNodeID_xt2,
const int admsNodeID_dt,
instanceSensStruct & instanceStruct,
modelSensStruct & modelStruct,
// basic variables
 double admsTemperature, double adms_vt_nom, double ADMSgmin_arg, std::vector <double> & d_staticContributions_dX, std::vector <double> & d_dynamicContributions_dX, const Instance & theInstance);

void evaluateInitialInstance(
instanceSensStruct & instanceStruct,
modelSensStruct & modelStruct,
 double admsTemperature,double adms_vt_nom, double ADMSgmin_arg, const Instance & theInstance);

void evaluateInitialModel(
modelSensStruct & modelStruct,
 double admsTemperature, double ADMSgmin_arg, const Instance & theInstance);

#endif // Xyce_ADMS_SENSITIVITIES


// Limited exponential --- NOT what verilog LRM says, but what qucs,
// ng-spice, and zspice do.

template <typename T>
T limexp(const T &x)
{
  if ((x) < 80.0)
  return (exp(x));
  else
  return (exp(80.0)*(x-79.0));
}


struct Traits: public DeviceTraits<Model, Instance, MOSFET1::Traits>
{
  static const char *name() {return "MVSG-HV HEMT MODEL";}
  static const char *deviceTypeName() {return "M level 2002";}

  static int numNodes() {return 4;}


  static bool modelRequired() {return true;}
  static bool isLinearDevice() {return false;}

  static Device *factory(const Configuration &configuration, const FactoryBlock &factory_block);
  static void loadModelParameters(ParametricData<Model> &model_parameters);
  static void loadInstanceParameters(ParametricData<Instance> &instance_parameters);
};

//-----------------------------------------------------------------------------
// Class         : Instance

//
// Purpose       : This class represents a single instance  of the
//                 device.  It mainly contains indices and pointers into
//                 the matrix equation (see the resistor instance class for
//                 more details).
//
// Special Notes :
// Creator       :
// Creation Date :
//-----------------------------------------------------------------------------
class Instance : public DeviceInstance
{
  friend class ParametricData<Instance>;
  friend class Model;
#ifdef Xyce_ADMS_SENSITIVITIES
  friend class InstanceSensitivity;
  friend class ModelSensitivity;
#endif // Xyce_ADMS_SENSITIVITIES
  friend struct Traits;

  public:
    Instance(
      const Configuration &       configuration,
      const InstanceBlock &       instance_block,
      Model &                     model,
      const FactoryBlock &        factory_block);

    ~Instance();

private:
    Instance(const Instance &);
    Instance &operator=(const Instance &);

public:
    void registerLIDs( const LocalIdVector & intLIDVecRef,
                       const LocalIdVector & extLIDVecRef );
    void registerStoreLIDs( const LocalIdVector & stoLIDVecRef );
    void setupPointers();

    void loadNodeSymbols(Util::SymbolTable &symbol_table) const;

    const JacobianStamp & jacobianStamp() const;
    void registerJacLIDs( const JacobianStamp & jacLIDVec );

    void registerBranchDataLIDs(const std::vector<int> & branchLIDVecRef);

    bool processParams();
    bool updateTemperature ( const double & temp = -999.0 );
    bool updateIntermediateVars ();
    bool updatePrimaryState ();
    bool updateSecondaryState ();

    // load functions, residual:
    bool loadDAEQVector ();
    bool loadDAEFVector ();

    // load functions, Jacobian:
    bool loadDAEdQdx ();
    bool loadDAEdFdx ();

      void collapseNodes();

  private:

  public:
    // iterator reference to the mvsg_cmc model which owns this instance.
    // Getters and setters
    Model &getModel()
    {
      return model_;
    }

  private:

    Model & model_;   //< Owning Model
    // Begin verilog Instance Variables
    //   Instance Parameters
    double w;
    double l;
    int ngf;
    double dtemp;
    //  Variables of global_instance scope
    double rcs_w;
    double rcd_w;
    double rg;
    double vgisi;
    double vdisi;
    double vti;
    double vdsati;
    double pdc;
    double idisi;
    double igs;
    double igd;
    double qgi;
     double d_qgi_dV_gi_si;
     double d_qgi_dV_di_si;
     double d_qgi_dTemp_dt_GND;
    double qdi;
     double d_qdi_dV_gi_si;
     double d_qdi_dV_di_si;
     double d_qdi_dTemp_dt_GND;
    double qsi;
     double d_qsi_dV_gi_si;
     double d_qsi_dV_di_si;
     double d_qsi_dTemp_dt_GND;
    double qbi;
    double gmi;
    double gdsi;
    double gmbsi;
    double cggi;
    double cgdi;
    double cgsi;
    double cgbi;
    double cdgi;
    double cddi;
    double cdsi;
    double cdbi;
    double csgi;
    double csdi;
    double cssi;
    double csbi;
    double cbgi;
    double cbdi;
    double cbsi;
    double cbbi;
    double cgs;
    double cgd;
    double t_total_k;
    double t_total_c;
    double t_delta_sh;
    double rs;
    double rd;
    // end verilog Instance Variables=====
    // Nodal LID Variables
    int li_d;
    int li_g;
    int li_s;
    int li_b;
    int li_di;
    int li_gi;
    int li_si;
    int li_fp1;
    int li_fp2;
    int li_fp3;
    int li_fp4;
    int li_drc;
    int li_src;
    int li_tr;
    int li_tr1;
    int li_xt1;
    int li_xt2;
    int li_dt;
    // end Nodal LID Variables
    // Branch LID Variables
    // end Branch LID Variables
    // Lead (branch) LID Variables
    int li_branch_id;
    int li_branch_ig;
    int li_branch_is;
    int li_branch_ib;
    // end Lead (branch) LID Variables
    // Jacobian  pointers
    double * f_tr1_Equ_d_Node_Ptr;
    double * f_tr1_Equ_g_Node_Ptr;
    double * f_tr1_Equ_tr1_Node_Ptr;
    double * f_tr1_Equ_tr_Node_Ptr;
    double * f_tr_Equ_tr1_Node_Ptr;
    double * f_tr_Equ_tr_Node_Ptr;
    double * f_fp4_Equ_dt_Node_Ptr;
    double * f_fp3_Equ_dt_Node_Ptr;
    double * f_fp4_Equ_b_Node_Ptr;
    double * f_fp4_Equ_fp3_Node_Ptr;
    double * f_fp3_Equ_b_Node_Ptr;
    double * f_fp3_Equ_fp3_Node_Ptr;
    double * f_fp4_Equ_fp4_Node_Ptr;
    double * f_fp3_Equ_fp4_Node_Ptr;
    double * f_fp4_Equ_gi_Node_Ptr;
    double * f_fp3_Equ_gi_Node_Ptr;
    double * f_fp4_Equ_s_Node_Ptr;
    double * f_fp3_Equ_s_Node_Ptr;
    double * f_gi_Equ_dt_Node_Ptr;
    double * f_gi_Equ_b_Node_Ptr;
    double * f_gi_Equ_fp3_Node_Ptr;
    double * f_gi_Equ_fp4_Node_Ptr;
    double * f_gi_Equ_gi_Node_Ptr;
    double * f_gi_Equ_s_Node_Ptr;
    double * f_s_Equ_dt_Node_Ptr;
    double * f_s_Equ_b_Node_Ptr;
    double * f_s_Equ_fp3_Node_Ptr;
    double * f_s_Equ_fp4_Node_Ptr;
    double * f_s_Equ_gi_Node_Ptr;
    double * f_s_Equ_s_Node_Ptr;
    double * f_gi_Equ_si_Node_Ptr;
    double * f_si_Equ_gi_Node_Ptr;
    double * f_si_Equ_si_Node_Ptr;
    double * f_si_Equ_dt_Node_Ptr;
    double * f_si_Equ_b_Node_Ptr;
    double * f_si_Equ_fp3_Node_Ptr;
    double * f_si_Equ_fp4_Node_Ptr;
    double * f_si_Equ_s_Node_Ptr;
    double * f_b_Equ_dt_Node_Ptr;
    double * f_b_Equ_b_Node_Ptr;
    double * f_b_Equ_fp3_Node_Ptr;
    double * f_b_Equ_fp4_Node_Ptr;
    double * f_b_Equ_gi_Node_Ptr;
    double * f_b_Equ_s_Node_Ptr;
    double * f_fp2_Equ_dt_Node_Ptr;
    double * f_fp3_Equ_fp2_Node_Ptr;
    double * f_fp2_Equ_b_Node_Ptr;
    double * f_fp2_Equ_fp2_Node_Ptr;
    double * f_fp2_Equ_fp3_Node_Ptr;
    double * f_fp2_Equ_gi_Node_Ptr;
    double * f_fp2_Equ_s_Node_Ptr;
    double * f_gi_Equ_fp2_Node_Ptr;
    double * f_s_Equ_fp2_Node_Ptr;
    double * f_si_Equ_fp2_Node_Ptr;
    double * f_b_Equ_fp2_Node_Ptr;
    double * f_fp1_Equ_dt_Node_Ptr;
    double * f_fp2_Equ_fp1_Node_Ptr;
    double * f_fp1_Equ_b_Node_Ptr;
    double * f_fp1_Equ_fp1_Node_Ptr;
    double * f_fp1_Equ_fp2_Node_Ptr;
    double * f_fp1_Equ_gi_Node_Ptr;
    double * f_fp1_Equ_s_Node_Ptr;
    double * f_gi_Equ_fp1_Node_Ptr;
    double * f_s_Equ_fp1_Node_Ptr;
    double * f_si_Equ_fp1_Node_Ptr;
    double * f_b_Equ_fp1_Node_Ptr;
    double * f_di_Equ_dt_Node_Ptr;
    double * f_fp1_Equ_di_Node_Ptr;
    double * f_di_Equ_b_Node_Ptr;
    double * f_di_Equ_di_Node_Ptr;
    double * f_di_Equ_fp1_Node_Ptr;
    double * f_di_Equ_gi_Node_Ptr;
    double * f_di_Equ_s_Node_Ptr;
    double * f_gi_Equ_di_Node_Ptr;
    double * f_s_Equ_di_Node_Ptr;
    double * f_si_Equ_di_Node_Ptr;
    double * f_b_Equ_di_Node_Ptr;
    double * f_src_Equ_dt_Node_Ptr;
    double * f_si_Equ_src_Node_Ptr;
    double * f_src_Equ_si_Node_Ptr;
    double * f_src_Equ_src_Node_Ptr;
    double * f_src_Equ_s_Node_Ptr;
    double * f_si_Equ_d_Node_Ptr;
    double * f_src_Equ_d_Node_Ptr;
    double * f_drc_Equ_drc_Node_Ptr;
    double * f_drc_Equ_fp4_Node_Ptr;
    double * f_fp4_Equ_drc_Node_Ptr;
    double * f_drc_Equ_s_Node_Ptr;
    double * f_drc_Equ_d_Node_Ptr;
    double * f_fp4_Equ_d_Node_Ptr;
    double * f_drc_Equ_dt_Node_Ptr;
    double * f_drc_Equ_tr_Node_Ptr;
    double * f_fp4_Equ_tr_Node_Ptr;
    double * f_di_Equ_si_Node_Ptr;
    double * f_xt1_Equ_xt2_Node_Ptr;
    double * f_xt1_Equ_dt_Node_Ptr;
    double * f_xt1_Equ_di_Node_Ptr;
    double * f_xt1_Equ_si_Node_Ptr;
    double * f_xt1_Equ_gi_Node_Ptr;
    double * f_xt1_Equ_xt1_Node_Ptr;
    double * f_xt2_Equ_xt2_Node_Ptr;
    double * f_xt2_Equ_xt1_Node_Ptr;
    double * f_di_Equ_xt2_Node_Ptr;
    double * f_si_Equ_xt2_Node_Ptr;
    double * f_d_Equ_dt_Node_Ptr;
    double * f_d_Equ_d_Node_Ptr;
    double * f_d_Equ_drc_Node_Ptr;
    double * f_s_Equ_src_Node_Ptr;
    double * f_g_Equ_g_Node_Ptr;
    double * f_g_Equ_gi_Node_Ptr;
    double * f_gi_Equ_g_Node_Ptr;
    double * f_gi_Equ_d_Node_Ptr;
    double * f_d_Equ_gi_Node_Ptr;
    double * f_d_Equ_s_Node_Ptr;
    double * f_s_Equ_d_Node_Ptr;
    double * f_d_Equ_b_Node_Ptr;
    double * f_b_Equ_d_Node_Ptr;
    double * f_dt_Equ_dt_Node_Ptr;
    double * f_dt_Equ_b_Node_Ptr;
    double * f_dt_Equ_fp3_Node_Ptr;
    double * f_dt_Equ_fp4_Node_Ptr;
    double * f_dt_Equ_gi_Node_Ptr;
    double * f_dt_Equ_s_Node_Ptr;
    double * f_dt_Equ_fp2_Node_Ptr;
    double * f_dt_Equ_fp1_Node_Ptr;
    double * f_dt_Equ_di_Node_Ptr;
    double * f_dt_Equ_si_Node_Ptr;
    double * f_dt_Equ_src_Node_Ptr;
    double * f_dt_Equ_d_Node_Ptr;
    double * f_dt_Equ_drc_Node_Ptr;
    double * f_dt_Equ_tr_Node_Ptr;
    double * q_tr1_Equ_d_Node_Ptr;
    double * q_tr1_Equ_g_Node_Ptr;
    double * q_tr1_Equ_tr1_Node_Ptr;
    double * q_tr1_Equ_tr_Node_Ptr;
    double * q_tr_Equ_tr1_Node_Ptr;
    double * q_tr_Equ_tr_Node_Ptr;
    double * q_fp4_Equ_dt_Node_Ptr;
    double * q_fp3_Equ_dt_Node_Ptr;
    double * q_fp4_Equ_b_Node_Ptr;
    double * q_fp4_Equ_fp3_Node_Ptr;
    double * q_fp3_Equ_b_Node_Ptr;
    double * q_fp3_Equ_fp3_Node_Ptr;
    double * q_fp4_Equ_fp4_Node_Ptr;
    double * q_fp3_Equ_fp4_Node_Ptr;
    double * q_fp4_Equ_gi_Node_Ptr;
    double * q_fp3_Equ_gi_Node_Ptr;
    double * q_fp4_Equ_s_Node_Ptr;
    double * q_fp3_Equ_s_Node_Ptr;
    double * q_gi_Equ_dt_Node_Ptr;
    double * q_gi_Equ_b_Node_Ptr;
    double * q_gi_Equ_fp3_Node_Ptr;
    double * q_gi_Equ_fp4_Node_Ptr;
    double * q_gi_Equ_gi_Node_Ptr;
    double * q_gi_Equ_s_Node_Ptr;
    double * q_s_Equ_dt_Node_Ptr;
    double * q_s_Equ_b_Node_Ptr;
    double * q_s_Equ_fp3_Node_Ptr;
    double * q_s_Equ_fp4_Node_Ptr;
    double * q_s_Equ_gi_Node_Ptr;
    double * q_s_Equ_s_Node_Ptr;
    double * q_gi_Equ_si_Node_Ptr;
    double * q_si_Equ_gi_Node_Ptr;
    double * q_si_Equ_si_Node_Ptr;
    double * q_si_Equ_dt_Node_Ptr;
    double * q_si_Equ_b_Node_Ptr;
    double * q_si_Equ_fp3_Node_Ptr;
    double * q_si_Equ_fp4_Node_Ptr;
    double * q_si_Equ_s_Node_Ptr;
    double * q_b_Equ_dt_Node_Ptr;
    double * q_b_Equ_b_Node_Ptr;
    double * q_b_Equ_fp3_Node_Ptr;
    double * q_b_Equ_fp4_Node_Ptr;
    double * q_b_Equ_gi_Node_Ptr;
    double * q_b_Equ_s_Node_Ptr;
    double * q_fp2_Equ_dt_Node_Ptr;
    double * q_fp3_Equ_fp2_Node_Ptr;
    double * q_fp2_Equ_b_Node_Ptr;
    double * q_fp2_Equ_fp2_Node_Ptr;
    double * q_fp2_Equ_fp3_Node_Ptr;
    double * q_fp2_Equ_gi_Node_Ptr;
    double * q_fp2_Equ_s_Node_Ptr;
    double * q_gi_Equ_fp2_Node_Ptr;
    double * q_s_Equ_fp2_Node_Ptr;
    double * q_si_Equ_fp2_Node_Ptr;
    double * q_b_Equ_fp2_Node_Ptr;
    double * q_fp1_Equ_dt_Node_Ptr;
    double * q_fp2_Equ_fp1_Node_Ptr;
    double * q_fp1_Equ_b_Node_Ptr;
    double * q_fp1_Equ_fp1_Node_Ptr;
    double * q_fp1_Equ_fp2_Node_Ptr;
    double * q_fp1_Equ_gi_Node_Ptr;
    double * q_fp1_Equ_s_Node_Ptr;
    double * q_gi_Equ_fp1_Node_Ptr;
    double * q_s_Equ_fp1_Node_Ptr;
    double * q_si_Equ_fp1_Node_Ptr;
    double * q_b_Equ_fp1_Node_Ptr;
    double * q_di_Equ_dt_Node_Ptr;
    double * q_fp1_Equ_di_Node_Ptr;
    double * q_di_Equ_b_Node_Ptr;
    double * q_di_Equ_di_Node_Ptr;
    double * q_di_Equ_fp1_Node_Ptr;
    double * q_di_Equ_gi_Node_Ptr;
    double * q_di_Equ_s_Node_Ptr;
    double * q_gi_Equ_di_Node_Ptr;
    double * q_s_Equ_di_Node_Ptr;
    double * q_si_Equ_di_Node_Ptr;
    double * q_b_Equ_di_Node_Ptr;
    double * q_src_Equ_dt_Node_Ptr;
    double * q_si_Equ_src_Node_Ptr;
    double * q_src_Equ_si_Node_Ptr;
    double * q_src_Equ_src_Node_Ptr;
    double * q_src_Equ_s_Node_Ptr;
    double * q_si_Equ_d_Node_Ptr;
    double * q_src_Equ_d_Node_Ptr;
    double * q_drc_Equ_drc_Node_Ptr;
    double * q_drc_Equ_fp4_Node_Ptr;
    double * q_fp4_Equ_drc_Node_Ptr;
    double * q_drc_Equ_s_Node_Ptr;
    double * q_drc_Equ_d_Node_Ptr;
    double * q_fp4_Equ_d_Node_Ptr;
    double * q_drc_Equ_dt_Node_Ptr;
    double * q_drc_Equ_tr_Node_Ptr;
    double * q_fp4_Equ_tr_Node_Ptr;
    double * q_di_Equ_si_Node_Ptr;
    double * q_xt1_Equ_xt2_Node_Ptr;
    double * q_xt1_Equ_dt_Node_Ptr;
    double * q_xt1_Equ_di_Node_Ptr;
    double * q_xt1_Equ_si_Node_Ptr;
    double * q_xt1_Equ_gi_Node_Ptr;
    double * q_xt1_Equ_xt1_Node_Ptr;
    double * q_xt2_Equ_xt2_Node_Ptr;
    double * q_xt2_Equ_xt1_Node_Ptr;
    double * q_di_Equ_xt2_Node_Ptr;
    double * q_si_Equ_xt2_Node_Ptr;
    double * q_d_Equ_dt_Node_Ptr;
    double * q_d_Equ_d_Node_Ptr;
    double * q_d_Equ_drc_Node_Ptr;
    double * q_s_Equ_src_Node_Ptr;
    double * q_g_Equ_g_Node_Ptr;
    double * q_g_Equ_gi_Node_Ptr;
    double * q_gi_Equ_g_Node_Ptr;
    double * q_gi_Equ_d_Node_Ptr;
    double * q_d_Equ_gi_Node_Ptr;
    double * q_d_Equ_s_Node_Ptr;
    double * q_s_Equ_d_Node_Ptr;
    double * q_d_Equ_b_Node_Ptr;
    double * q_b_Equ_d_Node_Ptr;
    double * q_dt_Equ_dt_Node_Ptr;
    double * q_dt_Equ_b_Node_Ptr;
    double * q_dt_Equ_fp3_Node_Ptr;
    double * q_dt_Equ_fp4_Node_Ptr;
    double * q_dt_Equ_gi_Node_Ptr;
    double * q_dt_Equ_s_Node_Ptr;
    double * q_dt_Equ_fp2_Node_Ptr;
    double * q_dt_Equ_fp1_Node_Ptr;
    double * q_dt_Equ_di_Node_Ptr;
    double * q_dt_Equ_si_Node_Ptr;
    double * q_dt_Equ_src_Node_Ptr;
    double * q_dt_Equ_d_Node_Ptr;
    double * q_dt_Equ_drc_Node_Ptr;
    double * q_dt_Equ_tr_Node_Ptr;
    // Jacobian offsets
    int A_tr1_Equ_d_NodeOffset;
    int A_tr1_Equ_g_NodeOffset;
    int A_tr1_Equ_tr1_NodeOffset;
    int A_tr1_Equ_tr_NodeOffset;
    int A_tr_Equ_tr1_NodeOffset;
    int A_tr_Equ_tr_NodeOffset;
    int A_fp4_Equ_dt_NodeOffset;
    int A_fp3_Equ_dt_NodeOffset;
    int A_fp4_Equ_b_NodeOffset;
    int A_fp4_Equ_fp3_NodeOffset;
    int A_fp3_Equ_b_NodeOffset;
    int A_fp3_Equ_fp3_NodeOffset;
    int A_fp4_Equ_fp4_NodeOffset;
    int A_fp3_Equ_fp4_NodeOffset;
    int A_fp4_Equ_gi_NodeOffset;
    int A_fp3_Equ_gi_NodeOffset;
    int A_fp4_Equ_s_NodeOffset;
    int A_fp3_Equ_s_NodeOffset;
    int A_gi_Equ_dt_NodeOffset;
    int A_gi_Equ_b_NodeOffset;
    int A_gi_Equ_fp3_NodeOffset;
    int A_gi_Equ_fp4_NodeOffset;
    int A_gi_Equ_gi_NodeOffset;
    int A_gi_Equ_s_NodeOffset;
    int A_s_Equ_dt_NodeOffset;
    int A_s_Equ_b_NodeOffset;
    int A_s_Equ_fp3_NodeOffset;
    int A_s_Equ_fp4_NodeOffset;
    int A_s_Equ_gi_NodeOffset;
    int A_s_Equ_s_NodeOffset;
    int A_gi_Equ_si_NodeOffset;
    int A_si_Equ_gi_NodeOffset;
    int A_si_Equ_si_NodeOffset;
    int A_si_Equ_dt_NodeOffset;
    int A_si_Equ_b_NodeOffset;
    int A_si_Equ_fp3_NodeOffset;
    int A_si_Equ_fp4_NodeOffset;
    int A_si_Equ_s_NodeOffset;
    int A_b_Equ_dt_NodeOffset;
    int A_b_Equ_b_NodeOffset;
    int A_b_Equ_fp3_NodeOffset;
    int A_b_Equ_fp4_NodeOffset;
    int A_b_Equ_gi_NodeOffset;
    int A_b_Equ_s_NodeOffset;
    int A_fp2_Equ_dt_NodeOffset;
    int A_fp3_Equ_fp2_NodeOffset;
    int A_fp2_Equ_b_NodeOffset;
    int A_fp2_Equ_fp2_NodeOffset;
    int A_fp2_Equ_fp3_NodeOffset;
    int A_fp2_Equ_gi_NodeOffset;
    int A_fp2_Equ_s_NodeOffset;
    int A_gi_Equ_fp2_NodeOffset;
    int A_s_Equ_fp2_NodeOffset;
    int A_si_Equ_fp2_NodeOffset;
    int A_b_Equ_fp2_NodeOffset;
    int A_fp1_Equ_dt_NodeOffset;
    int A_fp2_Equ_fp1_NodeOffset;
    int A_fp1_Equ_b_NodeOffset;
    int A_fp1_Equ_fp1_NodeOffset;
    int A_fp1_Equ_fp2_NodeOffset;
    int A_fp1_Equ_gi_NodeOffset;
    int A_fp1_Equ_s_NodeOffset;
    int A_gi_Equ_fp1_NodeOffset;
    int A_s_Equ_fp1_NodeOffset;
    int A_si_Equ_fp1_NodeOffset;
    int A_b_Equ_fp1_NodeOffset;
    int A_di_Equ_dt_NodeOffset;
    int A_fp1_Equ_di_NodeOffset;
    int A_di_Equ_b_NodeOffset;
    int A_di_Equ_di_NodeOffset;
    int A_di_Equ_fp1_NodeOffset;
    int A_di_Equ_gi_NodeOffset;
    int A_di_Equ_s_NodeOffset;
    int A_gi_Equ_di_NodeOffset;
    int A_s_Equ_di_NodeOffset;
    int A_si_Equ_di_NodeOffset;
    int A_b_Equ_di_NodeOffset;
    int A_src_Equ_dt_NodeOffset;
    int A_si_Equ_src_NodeOffset;
    int A_src_Equ_si_NodeOffset;
    int A_src_Equ_src_NodeOffset;
    int A_src_Equ_s_NodeOffset;
    int A_si_Equ_d_NodeOffset;
    int A_src_Equ_d_NodeOffset;
    int A_drc_Equ_drc_NodeOffset;
    int A_drc_Equ_fp4_NodeOffset;
    int A_fp4_Equ_drc_NodeOffset;
    int A_drc_Equ_s_NodeOffset;
    int A_drc_Equ_d_NodeOffset;
    int A_fp4_Equ_d_NodeOffset;
    int A_drc_Equ_dt_NodeOffset;
    int A_drc_Equ_tr_NodeOffset;
    int A_fp4_Equ_tr_NodeOffset;
    int A_di_Equ_si_NodeOffset;
    int A_xt1_Equ_xt2_NodeOffset;
    int A_xt1_Equ_dt_NodeOffset;
    int A_xt1_Equ_di_NodeOffset;
    int A_xt1_Equ_si_NodeOffset;
    int A_xt1_Equ_gi_NodeOffset;
    int A_xt1_Equ_xt1_NodeOffset;
    int A_xt2_Equ_xt2_NodeOffset;
    int A_xt2_Equ_xt1_NodeOffset;
    int A_di_Equ_xt2_NodeOffset;
    int A_si_Equ_xt2_NodeOffset;
    int A_d_Equ_dt_NodeOffset;
    int A_d_Equ_d_NodeOffset;
    int A_d_Equ_drc_NodeOffset;
    int A_s_Equ_src_NodeOffset;
    int A_g_Equ_g_NodeOffset;
    int A_g_Equ_gi_NodeOffset;
    int A_gi_Equ_g_NodeOffset;
    int A_gi_Equ_d_NodeOffset;
    int A_d_Equ_gi_NodeOffset;
    int A_d_Equ_s_NodeOffset;
    int A_s_Equ_d_NodeOffset;
    int A_d_Equ_b_NodeOffset;
    int A_b_Equ_d_NodeOffset;
    int A_dt_Equ_dt_NodeOffset;
    int A_dt_Equ_b_NodeOffset;
    int A_dt_Equ_fp3_NodeOffset;
    int A_dt_Equ_fp4_NodeOffset;
    int A_dt_Equ_gi_NodeOffset;
    int A_dt_Equ_s_NodeOffset;
    int A_dt_Equ_fp2_NodeOffset;
    int A_dt_Equ_fp1_NodeOffset;
    int A_dt_Equ_di_NodeOffset;
    int A_dt_Equ_si_NodeOffset;
    int A_dt_Equ_src_NodeOffset;
    int A_dt_Equ_d_NodeOffset;
    int A_dt_Equ_drc_NodeOffset;
    int A_dt_Equ_tr_NodeOffset;
    // end of Jacobian and pointers
   // node numbers
    static const int admsNodeID_d = 0;
    static const int admsNodeID_g = 1;
    static const int admsNodeID_s = 2;
    static const int admsNodeID_b = 3;
    static const int admsNodeID_di = 0+4;
    static const int admsNodeID_gi = 1+4;
    static const int admsNodeID_si = 2+4;
    static const int admsNodeID_fp1 = 3+4;
    static const int admsNodeID_fp2 = 4+4;
    static const int admsNodeID_fp3 = 5+4;
    static const int admsNodeID_fp4 = 6+4;
    static const int admsNodeID_drc = 7+4;
    static const int admsNodeID_src = 8+4;
    static const int admsNodeID_tr = 9+4;
    static const int admsNodeID_tr1 = 10+4;
    static const int admsNodeID_xt1 = 11+4;
    static const int admsNodeID_xt2 = 12+4;
    static const int admsNodeID_dt = 13+4;
    static const int admsNodeID_GND = -1;
   // end node numbers
   // Additional IDs for branch equations
   // end branch numbers
   // Probe numbers
    static const int admsProbeID_V_si_GND = 0;
    static const int admsProbeID_V_b_GND = 1;
    static const int admsProbeID_V_di_GND = 2;
    static const int admsProbeID_V_gi_GND = 3;
    static const int admsProbeID_V_drc_d = 4;
    static const int admsProbeID_V_gi_b = 5;
    static const int admsProbeID_V_s_b = 6;
    static const int admsProbeID_V_d_b = 7;
    static const int admsProbeID_V_d_s = 8;
    static const int admsProbeID_V_gi_d = 9;
    static const int admsProbeID_V_gi_s = 10;
    static const int admsProbeID_V_g_gi = 11;
    static const int admsProbeID_V_d_drc = 12;
    static const int admsProbeID_V_xt1_GND = 13;
    static const int admsProbeID_V_xt2_GND = 14;
    static const int admsProbeID_V_s_fp4 = 15;
    static const int admsProbeID_V_gi_fp4 = 16;
    static const int admsProbeID_V_b_fp3 = 17;
    static const int admsProbeID_V_fp4_fp3 = 18;
    static const int admsProbeID_V_s_fp3 = 19;
    static const int admsProbeID_V_gi_fp3 = 20;
    static const int admsProbeID_V_b_fp2 = 21;
    static const int admsProbeID_V_fp3_fp2 = 22;
    static const int admsProbeID_V_s_fp2 = 23;
    static const int admsProbeID_V_gi_fp2 = 24;
    static const int admsProbeID_V_b_fp1 = 25;
    static const int admsProbeID_V_fp2_fp1 = 26;
    static const int admsProbeID_V_s_fp1 = 27;
    static const int admsProbeID_V_gi_fp1 = 28;
    static const int admsProbeID_V_b_di = 29;
    static const int admsProbeID_V_fp1_di = 30;
    static const int admsProbeID_V_s_di = 31;
    static const int admsProbeID_V_gi_di = 32;
    static const int admsProbeID_V_drc_fp4 = 33;
    static const int admsProbeID_V_fp4_s = 34;
    static const int admsProbeID_V_fp4_d = 35;
    static const int admsProbeID_V_tr_GND = 36;
    static const int admsProbeID_V_tr1_tr = 37;
    static const int admsProbeID_V_d_g = 38;
    static const int admsProbeID_V_si_src = 39;
    static const int admsProbeID_V_src_s = 40;
    static const int admsProbeID_V_src_d = 41;
    static const int admsProbeID_V_gi_si = 42;
    static const int admsProbeID_V_di_si = 43;
    static const int admsProbeID_Temp_dt_GND = 44;
   // end probe numbers
   // Store LIDs
   // end store LIDs
   // Store LIDs for output vars
    int li_store_vgisi;
    int li_store_vdisi;
    int li_store_vti;
    int li_store_vdsati;
    int li_store_pdc;
    int li_store_idisi;
    int li_store_igs;
    int li_store_igd;
    int li_store_qgi;
    int li_store_qdi;
    int li_store_qsi;
    int li_store_qbi;
    int li_store_gmi;
    int li_store_gdsi;
    int li_store_gmbsi;
    int li_store_cggi;
    int li_store_cgdi;
    int li_store_cgsi;
    int li_store_cgbi;
    int li_store_cdgi;
    int li_store_cddi;
    int li_store_cdsi;
    int li_store_cdbi;
    int li_store_csgi;
    int li_store_csdi;
    int li_store_cssi;
    int li_store_csbi;
    int li_store_cbgi;
    int li_store_cbdi;
    int li_store_cbsi;
    int li_store_cbbi;
    int li_store_cgs;
    int li_store_cgd;
    int li_store_t_total_k;
    int li_store_t_total_c;
    int li_store_t_delta_sh;
    int li_store_rs;
    int li_store_rd;
   // end store LIDs for output vars
     // bools for collapsing nodes
     bool collapseNode_di;
     bool collapseNode_gi;
     bool collapseNode_si;
     bool collapseNode_fp1;
     bool collapseNode_fp2;
     bool collapseNode_fp3;
     bool collapseNode_fp4;
     bool collapseNode_drc;
     bool collapseNode_src;
     bool collapseNode_tr;
     bool collapseNode_tr1;
     bool collapseNode_xt1;
     bool collapseNode_xt2;
     bool collapseNode_dt;
 // Arrays to hold probes
 std::vector < double > probeVars;
 std::vector < std::vector < double > > d_probeVars;
 // Arrays to hold contributions
 // dynamic contributions are differentiated w.r.t time
 std::vector < double > staticContributions;
 std::vector < std::vector < double > > d_staticContributions;
 std::vector < double > dynamicContributions;
 std::vector < std::vector < double > > d_dynamicContributions;


    // this is what we'll use when any model uses $temperature.  We'll
    // set it in updateTemperature, and initialize it to whatever
    // is in devOptions when the instance is constructed.
    double admsTemperature;

    // vt at $temperature;
    double adms_vt_nom;


    // This one is for the annoying bogus "XyceADMSInstTemp" parameter
    // that we need so we can set it from the device manager when there's no
    // "TEMP" parameter to use
    double admsInstTemp;


    JacobianStamp jacStamp;
    IdVector nodeMap;
    PairMap pairToJacStampMap;

    // These instance-owned vectors are for storage of lead current data
    std::vector<double> leadCurrentF;
    std::vector<double> leadCurrentQ;


    };



namespace AnalogFunctions
{

      // Analog Function absfunc
template<typename ScalarT> ScalarT absfunc(ScalarT x)
{


    ScalarT absfunc;
{
absfunc = sqrt(((x*x)+(4.0*1e-5)));
}
return(absfunc);
}
// Derivative of Analog Function absfunc
double d_absfunc(double x  , double d_x  );
// Evaluator class for Analog Function absfunc
class absfuncEvaluator
{
  struct returnType
  {
     double value;
     double deriv_WRT_x;
  };
public:
  // constructor takes all same arguments as regular templated function,
  // even though it doesn't USE the output args
  absfuncEvaluator(double x);
  // function that returns the precomputed values.  This, too, takes
  // all the same arguments as the regular function, though it ONLY
  // uses the output arguments
  double getValues(double  x);
  // function that returns the total derivative of the function and its
  // output arguments with respect to some variable.  We pass in the
  // normal arguments(none of which are used) and the derivatives of those
  // arguments with respect to the desired variable.  We compute the
  // derivatives using the chain rule and our precomputed derivatives
  // with respect to input variables
double getDerivs(double x  , double d_x);
private:
  returnType absfuncReturn_;
  returnType evaluator_(double x);
};


      // Analog Function mmax
template<typename ScalarT> ScalarT mmax(ScalarT x, ScalarT y)
{


    ScalarT mmax;
{
mmax = (0.5*((x+y)+sqrt((((x-y)*(x-y))+(4.0*1e-5)))));
}
return(mmax);
}
// Derivative of Analog Function mmax
double d_mmax(double x , double y  , double d_x  , double d_y  );
// Evaluator class for Analog Function mmax
class mmaxEvaluator
{
  struct returnType
  {
     double value;
     double deriv_WRT_x;
     double deriv_WRT_y;
  };
public:
  // constructor takes all same arguments as regular templated function,
  // even though it doesn't USE the output args
  mmaxEvaluator(double x, double y);
  // function that returns the precomputed values.  This, too, takes
  // all the same arguments as the regular function, though it ONLY
  // uses the output arguments
  double getValues(double  x, double  y);
  // function that returns the total derivative of the function and its
  // output arguments with respect to some variable.  We pass in the
  // normal arguments(none of which are used) and the derivatives of those
  // arguments with respect to the desired variable.  We compute the
  // derivatives using the chain rule and our precomputed derivatives
  // with respect to input variables
double getDerivs(double x , double y  , double d_x, double d_y);
private:
  returnType mmaxReturn_;
  returnType evaluator_(double x, double y);
};


      // Analog Function explim
template<typename ScalarT> ScalarT explim(ScalarT x)
{


    ScalarT explim;
{
if ((x>50.0))
{
explim = (exp(50.0)*(1.0+(x-50.0)));
}
else
{
if ((x<(-50.0)))
{
explim = exp((-50.0));
}
else
{
explim = exp(x);
}
}
}
return(explim);
}
// Derivative of Analog Function explim
double d_explim(double x  , double d_x  );
// Evaluator class for Analog Function explim
class explimEvaluator
{
  struct returnType
  {
     double value;
     double deriv_WRT_x;
  };
public:
  // constructor takes all same arguments as regular templated function,
  // even though it doesn't USE the output args
  explimEvaluator(double x);
  // function that returns the precomputed values.  This, too, takes
  // all the same arguments as the regular function, though it ONLY
  // uses the output arguments
  double getValues(double  x);
  // function that returns the total derivative of the function and its
  // output arguments with respect to some variable.  We pass in the
  // normal arguments(none of which are used) and the derivatives of those
  // arguments with respect to the desired variable.  We compute the
  // derivatives using the chain rule and our precomputed derivatives
  // with respect to input variables
double getDerivs(double x  , double d_x);
private:
  returnType explimReturn_;
  returnType evaluator_(double x);
};


      // Analog Function calc_iq
template<typename ScalarT> ScalarT calc_iq(ScalarT & idsout, ScalarT & qgsout, ScalarT & qgdout, ScalarT & qcout, ScalarT & qbout, ScalarT & qsout, ScalarT & vtdibl, ScalarT & vdsat1, ScalarT vgsin, ScalarT vdsin, ScalarT qcbflag, ScalarT vcin, ScalarT vbin, ScalarT qgsflag, ScalarT tambin, ScalarT tnomin, ScalarT phitin, ScalarT w, ScalarT lin, ScalarT cgin, ScalarT cs, ScalarT cc, ScalarT cb, ScalarT vto, ScalarT ss, ScalarT delta1, ScalarT delta2, ScalarT nd, ScalarT alpha, ScalarT vel0, ScalarT mu0, ScalarT beta, ScalarT mtheta, ScalarT vtheta, ScalarT vtzeta, ScalarT dibsat, ScalarT epsilon, ScalarT vzeta, ScalarT lambda, ScalarT ngf, ScalarT type)
{


    ScalarT calc_iq;
ScalarT alpha_phit;
ScalarT delta;
ScalarT n;
ScalarT vtof;
ScalarT vsatdibl;
ScalarT ffs;
ScalarT two_n_phit;
ScalarT qref;
ScalarT etas;
ScalarT qinvs;
ScalarT muf;
ScalarT vx;
ScalarT vxf;
ScalarT n0;
ScalarT ffs0;
ScalarT two_n_phit0;
ScalarT qref0;
ScalarT etas0;
ScalarT qinvs0;
ScalarT muf0;
ScalarT vx0;
ScalarT ff;
ScalarT eta;
ScalarT qinvv;
ScalarT ff0;
ScalarT eta0;
ScalarT qinvv0;
ScalarT vdsats;
ScalarT vdsats1;
ScalarT vdsat;
ScalarT fsd;
ScalarT vdx;
ScalarT fds;
ScalarT vsx;
ScalarT ffd;
ScalarT etad;
ScalarT qinvd;
ScalarT vdsc;
ScalarT fsat;
ScalarT vel;
ScalarT vdsats0;
ScalarT vdsats10;
ScalarT vdsat10;
ScalarT fsd0;
ScalarT vdx0;
ScalarT fds0;
ScalarT vsx0;
ScalarT ffd0;
ScalarT etad0;
ScalarT qinvd0;
ScalarT qs2;
ScalarT qs3;
ScalarT qd2;
ScalarT qd3;
ScalarT qsqd;
ScalarT qinvdd;
ScalarT qd1;
ScalarT qs;
ScalarT qd;
ScalarT etac;
ScalarT etab;
ScalarT etags;
ScalarT exparg;
ScalarT myarg;
ScalarT absvdsin;
ScalarT vgdin;
ScalarT exparg0;
ScalarT myarg0;
{
absvdsin = absfunc<ScalarT>(vdsin);
vgdin = (vgsin-vdsin);
alpha_phit = (alpha*phitin);
n = ((ss/(2.30258509299404568401*phitin))+(nd*absvdsin));
vtof = (vto+(vtzeta*(tambin-tnomin)));
if ((dibsat!=0))
{
vsatdibl = (absvdsin/pow((1.0+pow((absvdsin/dibsat),beta)),(1.0/beta)));
}
else
{
vsatdibl = 0;
}
delta = ((delta1-(vsatdibl*delta2))*absvdsin);
vtdibl = (vtof-delta);
two_n_phit = ((2.0*n)*phitin);
qref = (cgin*two_n_phit);
myarg = (vtdibl-(alpha_phit/2.0));
exparg = ((mmax<ScalarT>(vgsin,vgdin)-myarg)/alpha_phit);
if ((exparg>50.0))
{
ff = 0.0;
}
else
{
if ((exparg<(-50.0)))
{
ff = 1.0;
}
else
{
ff = (1.0/(1.0+exp(exparg)));
}
}
eta = ((mmax<ScalarT>(vgsin,vgdin)-(vtdibl-((0.1*alpha_phit)*ff)))/two_n_phit);
if ((eta>50.0))
{
qinvv = (qref*eta);
}
else
{
if ((eta<(-50.0)))
{
qinvv = 0;
}
else
{
qinvv = (qref*log((1.0+exp(eta))));
}
}
muf = (mu0/(pow((tambin/tnomin),epsilon)*(1.0+((mtheta*qinvv)/cgin))));
vx = (((vel0*((1.0+(vzeta*tnomin))/(1.0+(vzeta*tambin))))*(1.0+((lambda*absvdsin)/lin)))/(1.0+((vtheta*qinvv)/cgin)));
vxf = (((((2.0*ff)*phitin)*muf)/lin)+((1.0-ff)*vx));
vdsats = ((vx*lin)/muf);
vdsats1 = ((vdsats*sqrt((1.0+(((2.0*qinvv)/cgin)/vdsats))))-vdsats);
vdsat = ((vdsats*(1.0-ff))+(two_n_phit*ff));
vdsat1 = ((vdsats1*(1.0-ff))+(two_n_phit*ff));
fsd = (1.0/pow((1.0+pow(mmax<ScalarT>(0,(vdsin/vdsat1)),beta)),(1.0/beta)));
vdx = (vdsin*fsd);
fds = (1.0/pow((1.0+pow(mmax<ScalarT>(0,((-vdsin)/vdsat1)),beta)),(1.0/beta)));
vsx = ((-vdsin)*fds);
exparg = ((vgsin-myarg)/alpha_phit);
if ((exparg>50.0))
{
ffs = 0.0;
}
else
{
if ((exparg<(-50.0)))
{
ffs = 1.0;
}
else
{
ffs = (1.0/(1.0+exp(exparg)));
}
}
etas = (((vgdin-vsx)-(vtdibl-((0.1*alpha_phit)*ffs)))/two_n_phit);
if ((etas>50.0))
{
qinvs = (qref*etas);
}
else
{
if ((etas<(-50.0)))
{
qinvs = 0;
}
else
{
qinvs = (qref*log((1.0+exp(etas))));
}
}
exparg = ((vgdin-myarg)/alpha_phit);
if ((exparg>50.0))
{
ffd = 0.0;
}
else
{
if ((exparg<(-50.0)))
{
ffd = 1.0;
}
else
{
ffd = (1.0/(1.0+exp(exparg)));
}
}
etad = (((vgsin-vdx)-(vtdibl-((0.1*alpha_phit)*ffd)))/two_n_phit);
if ((etad>50.0))
{
qinvd = (qref*etad);
}
else
{
if ((etad<(-50.0)))
{
qinvd = 0;
}
else
{
qinvd = (qref*log((1.0+exp(etad))));
}
}
vdsc = ((qinvs-qinvd)/cgin);
myarg = (vdsc/vdsat);
fsat = (myarg/pow((1.0+pow(absfunc<ScalarT>(myarg),beta)),(1.0/beta)));
vel = (vxf*fsat);
idsout = (((((type*w)*ngf)*0.5)*(qinvs+qinvd))*vel);
n0 = (ss/(2.30258509299404568401*phitin));
two_n_phit0 = ((2.0*n0)*phitin);
qref0 = (cgin*two_n_phit0);
myarg0 = (vtof-(alpha_phit/2.0));
exparg0 = ((mmax<ScalarT>(vgsin,vgdin)-myarg0)/alpha_phit);
if ((exparg0>50.0))
{
ff0 = 0.0;
}
else
{
if ((exparg0<(-50.0)))
{
ff0 = 1.0;
}
else
{
ff0 = (1.0/(1.0+exp(exparg0)));
}
}
eta0 = ((mmax<ScalarT>(vgsin,vgdin)-(vtof-((0.1*alpha_phit)*ff0)))/two_n_phit0);
if ((eta0>50.0))
{
qinvv0 = (qref0*eta0);
}
else
{
if ((eta0<(-50.0)))
{
qinvv0 = 0;
}
else
{
qinvv0 = (qref0*log((1.0+exp(eta0))));
}
}
muf0 = (mu0/pow((tambin/tnomin),epsilon));
vx0 = (vel0*((1.0+(vzeta*tnomin))/(1.0+(vzeta*tambin))));
vdsats0 = ((vx0*lin)/muf0);
vdsats10 = ((vdsats0*sqrt((1.0+(((2.0*qinvv0)/cgin)/vdsats0))))-vdsats0);
vdsat10 = ((vdsats10*(1.0-ff0))+(two_n_phit0*ff0));
fsd0 = (1.0/pow((1.0+pow(mmax<ScalarT>(0,(vdsin/vdsat10)),beta)),(1.0/beta)));
vdx0 = (vdsin*fsd0);
fds0 = (1.0/pow((1.0+pow(mmax<ScalarT>(0,((-vdsin)/vdsat10)),beta)),(1.0/beta)));
vsx0 = ((-vdsin)*fds0);
exparg0 = ((vgsin-myarg0)/alpha_phit);
if ((exparg0>50.0))
{
ffs0 = 0.0;
}
else
{
if ((exparg0<(-50.0)))
{
ffs0 = 1.0;
}
else
{
ffs0 = (1.0/(1.0+exp(exparg0)));
}
}
etas0 = (((vgdin-vsx0)-(vtof-((0.1*alpha_phit)*ffs0)))/two_n_phit0);
if ((etas0>50.0))
{
qinvs0 = (qref0*etas0);
}
else
{
if ((etas0<(-50.0)))
{
qinvs0 = 0;
}
else
{
qinvs0 = (qref0*log((1.0+exp(etas0))));
}
}
exparg0 = ((vgdin-myarg0)/alpha_phit);
if ((exparg0>50.0))
{
ffd0 = 0.0;
}
else
{
if ((exparg0<(-50.0)))
{
ffd0 = 1.0;
}
else
{
ffd0 = (1.0/(1.0+exp(exparg0)));
}
}
etad0 = (((vgsin-vdx0)-(vtof-((0.1*alpha_phit)*ffd0)))/two_n_phit0);
if ((etad0>50.0))
{
qinvd0 = (qref0*etad0);
}
else
{
if ((etad0<(-50.0)))
{
qinvd0 = 0;
}
else
{
qinvd0 = (qref0*log((1.0+exp(etad0))));
}
}
qs2 = ((qinvs0*qinvs0)+1e-38);
qs3 = ((qs2*qinvs0)+1e-57);
qd2 = ((qinvd0*qinvd0)+1e-38);
qd3 = ((qd2*qinvd0)+1e-57);
qsqd = ((qinvs0*qinvd0)+1e-38);
qinvdd = (((2.0/3.0)*((qs2+qd2)+qsqd))/((qinvs0+qinvd0)+2e-19));
qd1 = ((2.0*((((2.0*qs3)+(3.0*qd3))+((4.0*qs2)*qinvd0))+((6.0*qd2)*qinvs0)))/(15.0*((qs2+qd2)+(2.0*qsqd))));
qs = (qinvdd-qd1);
qd = qd1;
qgsout = ((((w*ngf)*lin)*type)*qs);
qgdout = ((((w*ngf)*lin)*type)*qd);
if ((qcbflag==1))
{
etac = ((vcin-(vtof-(0.5*alpha_phit)))/two_n_phit0);
if ((etac>50.0))
{
exparg = etac;
}
else
{
if ((etac<(-50.0)))
{
exparg = 0;
}
else
{
exparg = log((1.0+exp(etac)));
}
}
qcout = (((((w*ngf)*type)*cc)*two_n_phit0)*exparg);
etab = ((vbin-(vtof-(0.5*alpha_phit)))/two_n_phit0);
if ((etab>50.0))
{
exparg = etab;
}
else
{
if ((etab<(-50.0)))
{
exparg = 0;
}
else
{
exparg = log((1.0+exp(etab)));
}
}
qbout = (((((w*ngf)*type)*cb)*two_n_phit0)*exparg);
}
else
{
qcout = 0;
qbout = 0;
}
if ((qgsflag==1))
{
etags = ((vgsin-(vtof-(0.5*alpha_phit)))/two_n_phit0);
if ((etags>50.0))
{
exparg = etags;
}
else
{
if ((etags<(-50.0)))
{
exparg = 0;
}
else
{
exparg = log((1.0+exp(etags)));
}
}
qsout = (((((w*ngf)*type)*cs)*two_n_phit0)*exparg);
}
else
{
qsout = 0;
}
calc_iq = idsout;
}
return(calc_iq);
}
// Derivative of Analog Function calc_iq
double d_calc_iq(double idsout , double qgsout , double qgdout , double qcout , double qbout , double qsout , double vtdibl , double vdsat1 , double vgsin , double vdsin , double qcbflag , double vcin , double vbin , double qgsflag , double tambin , double tnomin , double phitin , double w , double lin , double cgin , double cs , double cc , double cb , double vto , double ss , double delta1 , double delta2 , double nd , double alpha , double vel0 , double mu0 , double beta , double mtheta , double vtheta , double vtzeta , double dibsat , double epsilon , double vzeta , double lambda , double ngf , double type  , double & d_idsout  , double & d_qgsout  , double & d_qgdout  , double & d_qcout  , double & d_qbout  , double & d_qsout  , double & d_vtdibl  , double & d_vdsat1  , double d_vgsin  , double d_vdsin  , double d_qcbflag  , double d_vcin  , double d_vbin  , double d_qgsflag  , double d_tambin  , double d_tnomin  , double d_phitin  , double d_w  , double d_lin  , double d_cgin  , double d_cs  , double d_cc  , double d_cb  , double d_vto  , double d_ss  , double d_delta1  , double d_delta2  , double d_nd  , double d_alpha  , double d_vel0  , double d_mu0  , double d_beta  , double d_mtheta  , double d_vtheta  , double d_vtzeta  , double d_dibsat  , double d_epsilon  , double d_vzeta  , double d_lambda  , double d_ngf  , double d_type  );
// Evaluator class for Analog Function calc_iq
class calc_iqEvaluator
{
  struct returnType
  {
     double value;
     double deriv_WRT_vgsin;
     double deriv_WRT_vdsin;
     double deriv_WRT_qcbflag;
     double deriv_WRT_vcin;
     double deriv_WRT_vbin;
     double deriv_WRT_qgsflag;
     double deriv_WRT_tambin;
     double deriv_WRT_tnomin;
     double deriv_WRT_phitin;
     double deriv_WRT_w;
     double deriv_WRT_lin;
     double deriv_WRT_cgin;
     double deriv_WRT_cs;
     double deriv_WRT_cc;
     double deriv_WRT_cb;
     double deriv_WRT_vto;
     double deriv_WRT_ss;
     double deriv_WRT_delta1;
     double deriv_WRT_delta2;
     double deriv_WRT_nd;
     double deriv_WRT_alpha;
     double deriv_WRT_vel0;
     double deriv_WRT_mu0;
     double deriv_WRT_beta;
     double deriv_WRT_mtheta;
     double deriv_WRT_vtheta;
     double deriv_WRT_vtzeta;
     double deriv_WRT_dibsat;
     double deriv_WRT_epsilon;
     double deriv_WRT_vzeta;
     double deriv_WRT_lambda;
     double deriv_WRT_ngf;
     double deriv_WRT_type;
  };
public:
  // constructor takes all same arguments as regular templated function,
  // even though it doesn't USE the output args
  calc_iqEvaluator(double idsout, double qgsout, double qgdout, double qcout, double qbout, double qsout, double vtdibl, double vdsat1, double vgsin, double vdsin, double qcbflag, double vcin, double vbin, double qgsflag, double tambin, double tnomin, double phitin, double w, double lin, double cgin, double cs, double cc, double cb, double vto, double ss, double delta1, double delta2, double nd, double alpha, double vel0, double mu0, double beta, double mtheta, double vtheta, double vtzeta, double dibsat, double epsilon, double vzeta, double lambda, double ngf, double type);
  // function that returns the precomputed values.  This, too, takes
  // all the same arguments as the regular function, though it ONLY
  // uses the output arguments
  double getValues(double &  idsout, double &  qgsout, double &  qgdout, double &  qcout, double &  qbout, double &  qsout, double &  vtdibl, double &  vdsat1, double  vgsin, double  vdsin, double  qcbflag, double  vcin, double  vbin, double  qgsflag, double  tambin, double  tnomin, double  phitin, double  w, double  lin, double  cgin, double  cs, double  cc, double  cb, double  vto, double  ss, double  delta1, double  delta2, double  nd, double  alpha, double  vel0, double  mu0, double  beta, double  mtheta, double  vtheta, double  vtzeta, double  dibsat, double  epsilon, double  vzeta, double  lambda, double  ngf, double  type);
  // function that returns the total derivative of the function and its
  // output arguments with respect to some variable.  We pass in the
  // normal arguments(none of which are used) and the derivatives of those
  // arguments with respect to the desired variable.  We compute the
  // derivatives using the chain rule and our precomputed derivatives
  // with respect to input variables
double getDerivs(double idsout , double qgsout , double qgdout , double qcout , double qbout , double qsout , double vtdibl , double vdsat1 , double vgsin , double vdsin , double qcbflag , double vcin , double vbin , double qgsflag , double tambin , double tnomin , double phitin , double w , double lin , double cgin , double cs , double cc , double cb , double vto , double ss , double delta1 , double delta2 , double nd , double alpha , double vel0 , double mu0 , double beta , double mtheta , double vtheta , double vtzeta , double dibsat , double epsilon , double vzeta , double lambda , double ngf , double type  , double & d_idsout, double & d_qgsout, double & d_qgdout, double & d_qcout, double & d_qbout, double & d_qsout, double & d_vtdibl, double & d_vdsat1, double d_vgsin, double d_vdsin, double d_qcbflag, double d_vcin, double d_vbin, double d_qgsflag, double d_tambin, double d_tnomin, double d_phitin, double d_w, double d_lin, double d_cgin, double d_cs, double d_cc, double d_cb, double d_vto, double d_ss, double d_delta1, double d_delta2, double d_nd, double d_alpha, double d_vel0, double d_mu0, double d_beta, double d_mtheta, double d_vtheta, double d_vtzeta, double d_dibsat, double d_epsilon, double d_vzeta, double d_lambda, double d_ngf, double d_type);
private:
  returnType calc_iqReturn_;
  returnType idsoutReturn_;
  returnType qgsoutReturn_;
  returnType qgdoutReturn_;
  returnType qcoutReturn_;
  returnType qboutReturn_;
  returnType qsoutReturn_;
  returnType vtdiblReturn_;
  returnType vdsat1Return_;
  returnType evaluator_(returnType & idsout, returnType & qgsout, returnType & qgdout, returnType & qcout, returnType & qbout, returnType & qsout, returnType & vtdibl, returnType & vdsat1, double vgsin, double vdsin, double qcbflag, double vcin, double vbin, double qgsflag, double tambin, double tnomin, double phitin, double w, double lin, double cgin, double cs, double cc, double cb, double vto, double ss, double delta1, double delta2, double nd, double alpha, double vel0, double mu0, double beta, double mtheta, double vtheta, double vtzeta, double dibsat, double epsilon, double vzeta, double lambda, double ngf, double type);
};


      // Analog Function calc_ig
template<typename ScalarT> ScalarT calc_ig(ScalarT & isdiodeout, ScalarT & isrecout, ScalarT vgin, ScalarT phitin, ScalarT vgsatin, ScalarT alphagin, ScalarT fracin, ScalarT pg_paramin, ScalarT pbdgin, ScalarT vbdgin, ScalarT tambin, ScalarT tnomin, ScalarT w, ScalarT ngf, ScalarT ijin, ScalarT kbdgatein, ScalarT vgsatqin, ScalarT betarecin, ScalarT irecin, ScalarT pgsrecin, ScalarT pg_param1, ScalarT vjg, ScalarT type)
{


    ScalarT calc_ig;
ScalarT igout;
ScalarT alpha_phit;
ScalarT t0;
ScalarT ffvgin;
ScalarT pgin;
ScalarT iginbd;
ScalarT tfacdiode;
ScalarT igindiode;
ScalarT frecgin;
ScalarT iginrec;
ScalarT expbdarg1;
ScalarT expbdarg2;
ScalarT expbd1;
ScalarT expbd2;
ScalarT expphib;
ScalarT expffvarg;
ScalarT expiforarg;
ScalarT expifor;
ScalarT expirevarg;
ScalarT expirev;
{
alpha_phit = (alphagin*phitin);
expphib = ((pg_param1/phitin)*(-vjg));
t0 = explim<ScalarT>(expphib);
expffvarg = ((vgin-(vgsatin-((alphagin*alpha_phit)/2.0)))/(alphagin*alpha_phit));
if ((expffvarg>50.0))
{
ffvgin = 0.0;
}
else
{
if ((expffvarg<(-50.0)))
{
ffvgin = 1.0;
}
else
{
ffvgin = (1.0/(1.0+exp(expffvarg)));
}
}
pgin = ((fracin*pg_paramin)+(((1.0-fracin)*pg_paramin)*ffvgin));
expbdarg1 = ((pbdgin*((-vgin)-vbdgin))+expphib);
expbdarg2 = (((-pbdgin)*vbdgin)+expphib);
expbd1 = explim<ScalarT>(expbdarg1);
expbd2 = explim<ScalarT>(expbdarg2);
iginbd = (expbd1-expbd2);
tfacdiode = pow((tambin/tnomin),3.0);
isdiodeout = ((((type*w)*ngf)*ijin)*tfacdiode);
expiforarg = (((pgin/phitin)*vgin)+expphib);
expifor = explim<ScalarT>(expiforarg);
igindiode = (isdiodeout*((expifor-(kbdgatein*iginbd))-t0));
frecgin = ((-vgin)/pow((1.0+pow(absfunc<ScalarT>((vgin/vgsatqin)),betarecin)),(1.0/betarecin)));
isrecout = ((((((-type)*w)*ngf)*irecin)*tfacdiode)*1.0);
expirevarg = ((pgsrecin/phitin)*frecgin);
expirev = explim<ScalarT>(expirevarg);
iginrec = (isrecout*(expirev-1.0));
igout = (igindiode+iginrec);
calc_ig = igout;
}
return(calc_ig);
}
// Derivative of Analog Function calc_ig
double d_calc_ig(double isdiodeout , double isrecout , double vgin , double phitin , double vgsatin , double alphagin , double fracin , double pg_paramin , double pbdgin , double vbdgin , double tambin , double tnomin , double w , double ngf , double ijin , double kbdgatein , double vgsatqin , double betarecin , double irecin , double pgsrecin , double pg_param1 , double vjg , double type  , double & d_isdiodeout  , double & d_isrecout  , double d_vgin  , double d_phitin  , double d_vgsatin  , double d_alphagin  , double d_fracin  , double d_pg_paramin  , double d_pbdgin  , double d_vbdgin  , double d_tambin  , double d_tnomin  , double d_w  , double d_ngf  , double d_ijin  , double d_kbdgatein  , double d_vgsatqin  , double d_betarecin  , double d_irecin  , double d_pgsrecin  , double d_pg_param1  , double d_vjg  , double d_type  );
// Evaluator class for Analog Function calc_ig
class calc_igEvaluator
{
  struct returnType
  {
     double value;
     double deriv_WRT_vgin;
     double deriv_WRT_phitin;
     double deriv_WRT_vgsatin;
     double deriv_WRT_alphagin;
     double deriv_WRT_fracin;
     double deriv_WRT_pg_paramin;
     double deriv_WRT_pbdgin;
     double deriv_WRT_vbdgin;
     double deriv_WRT_tambin;
     double deriv_WRT_tnomin;
     double deriv_WRT_w;
     double deriv_WRT_ngf;
     double deriv_WRT_ijin;
     double deriv_WRT_kbdgatein;
     double deriv_WRT_vgsatqin;
     double deriv_WRT_betarecin;
     double deriv_WRT_irecin;
     double deriv_WRT_pgsrecin;
     double deriv_WRT_pg_param1;
     double deriv_WRT_vjg;
     double deriv_WRT_type;
  };
public:
  // constructor takes all same arguments as regular templated function,
  // even though it doesn't USE the output args
  calc_igEvaluator(double isdiodeout, double isrecout, double vgin, double phitin, double vgsatin, double alphagin, double fracin, double pg_paramin, double pbdgin, double vbdgin, double tambin, double tnomin, double w, double ngf, double ijin, double kbdgatein, double vgsatqin, double betarecin, double irecin, double pgsrecin, double pg_param1, double vjg, double type);
  // function that returns the precomputed values.  This, too, takes
  // all the same arguments as the regular function, though it ONLY
  // uses the output arguments
  double getValues(double &  isdiodeout, double &  isrecout, double  vgin, double  phitin, double  vgsatin, double  alphagin, double  fracin, double  pg_paramin, double  pbdgin, double  vbdgin, double  tambin, double  tnomin, double  w, double  ngf, double  ijin, double  kbdgatein, double  vgsatqin, double  betarecin, double  irecin, double  pgsrecin, double  pg_param1, double  vjg, double  type);
  // function that returns the total derivative of the function and its
  // output arguments with respect to some variable.  We pass in the
  // normal arguments(none of which are used) and the derivatives of those
  // arguments with respect to the desired variable.  We compute the
  // derivatives using the chain rule and our precomputed derivatives
  // with respect to input variables
double getDerivs(double isdiodeout , double isrecout , double vgin , double phitin , double vgsatin , double alphagin , double fracin , double pg_paramin , double pbdgin , double vbdgin , double tambin , double tnomin , double w , double ngf , double ijin , double kbdgatein , double vgsatqin , double betarecin , double irecin , double pgsrecin , double pg_param1 , double vjg , double type  , double & d_isdiodeout, double & d_isrecout, double d_vgin, double d_phitin, double d_vgsatin, double d_alphagin, double d_fracin, double d_pg_paramin, double d_pbdgin, double d_vbdgin, double d_tambin, double d_tnomin, double d_w, double d_ngf, double d_ijin, double d_kbdgatein, double d_vgsatqin, double d_betarecin, double d_irecin, double d_pgsrecin, double d_pg_param1, double d_vjg, double d_type);
private:
  returnType calc_igReturn_;
  returnType isdiodeoutReturn_;
  returnType isrecoutReturn_;
  returnType evaluator_(returnType & isdiodeout, returnType & isrecout, double vgin, double phitin, double vgsatin, double alphagin, double fracin, double pg_paramin, double pbdgin, double vbdgin, double tambin, double tnomin, double w, double ngf, double ijin, double kbdgatein, double vgsatqin, double betarecin, double irecin, double pgsrecin, double pg_param1, double vjg, double type);
};

}


//-----------------------------------------------------------------------------
// Class         : Model

// Purpose       :
// Special Notes :
// Creator       :
// Creation Date :
//-----------------------------------------------------------------------------
class Model : public DeviceModel
{
    typedef std::vector<Instance *> InstanceVector;

    friend class ParametricData<Model>;
    friend class Instance;
#ifdef Xyce_ADMS_SENSITIVITIES
    friend class InstanceSensitivity;
    friend class ModelSensitivity;
#endif // Xyce_ADMS_SENSITIVITIES
    friend struct Traits;

  public:
    Model(
      const Configuration &       configuration,
      const ModelBlock &          model_block,
      const FactoryBlock &        factory_block);

    ~Model();

private:
    Model(const Model &);
    Model &operator=(const Model &);

public:
    virtual void forEachInstance(DeviceInstanceOp &op) const /* override */;
    virtual std::ostream &printOutInstances(std::ostream &os) const;
    bool processParams();
    bool processInstanceParams();

  private:

  public:
    void addInstance(Instance *instance)
    {
      instanceContainer.push_back(instance);
    }

    void setupBaseInstanceContainer()
    {
      std::vector<Instance*>::iterator iter = instanceContainer.begin();
      std::vector<Instance*>::iterator end   = instanceContainer.end();
      for ( ; iter!=end; ++iter)
      {
      Xyce::Device::DeviceModel::baseInstanceContainer.push_back( static_cast<Xyce::Device::DeviceInstance *>(*iter) );
    }
  }

  private:
    std::vector<Instance*> instanceContainer;

  private:

    // This one is for the annoying bogus "XyceADMSInstTemp" parameter
    // that we need so we can set it from the device manager when there's no
    // "TEMP" model parameter to use
    double admsModTemp;
// Begin verilog Model Variables
//   Model Parameters
    double version;
    double tnom;
    int type;
    double cg;
    double cofsm;
    double cofdm;
    double cofdsm;
    double cofdsubm;
    double cofssubm;
    double cofgsubm;
    double rsh;
    double rcs;
    double rcd;
    double vx0;
    double mu0;
    double beta;
    double vto;
    double ss;
    double delta1;
    double delta2;
    double dibsat;
    double nd;
    double alpha;
    double lambda;
    double vtheta;
    double mtheta;
    double vzeta;
    double vtzeta;
    double epsilon;
    double rct1;
    double rct2;
    int flagres;
    double lgs;
    double vtors;
    double cgrs;
    double vx0rs;
    double mu0rs;
    double betars;
    double delta1rs;
    double srs;
    double ndrs;
    double vthetars;
    double mthetars;
    double alphars;
    double lgd;
    double vtord;
    double cgrd;
    double vx0rd;
    double mu0rd;
    double betard;
    double delta1rd;
    double srd;
    double ndrd;
    double vthetard;
    double mthetard;
    double alphard;
    int flagfp1;
    double lgfp1;
    double vtofp1;
    double cgfp1;
    int flagfp1s;
    double cfp1s;
    double ccfp1;
    double cbfp1;
    double vx0fp1;
    double mu0fp1;
    double betafp1;
    double delta1fp1;
    double sfp1;
    double ndfp1;
    double vthetafp1;
    double mthetafp1;
    double alphafp1;
    int flagfp2;
    double lgfp2;
    double vtofp2;
    double cgfp2;
    int flagfp2s;
    double cfp2s;
    double ccfp2;
    double cbfp2;
    double vx0fp2;
    double mu0fp2;
    double betafp2;
    double delta1fp2;
    double sfp2;
    double ndfp2;
    double vthetafp2;
    double mthetafp2;
    double alphafp2;
    int flagfp3;
    double lgfp3;
    double vtofp3;
    double cgfp3;
    int flagfp3s;
    double cfp3s;
    double ccfp3;
    double cbfp3;
    double vx0fp3;
    double mu0fp3;
    double betafp3;
    double delta1fp3;
    double sfp3;
    double ndfp3;
    double vthetafp3;
    double mthetafp3;
    double alphafp3;
    int flagfp4;
    double lgfp4;
    double vtofp4;
    double cgfp4;
    int flagfp4s;
    double cfp4s;
    double ccfp4;
    double cbfp4;
    double vx0fp4;
    double mu0fp4;
    double betafp4;
    double delta1fp4;
    double sfp4;
    double ndfp4;
    double vthetafp4;
    double mthetafp4;
    double alphafp4;
    int igmod;
    double rgsp;
    double vjg;
    double pg_param1;
    double pg_params;
    double ijs;
    double vgsats;
    double fracs;
    double alphags;
    double pg_paramd;
    double ijd;
    double vgsatd;
    double fracd;
    double alphagd;
    double pgsrecs;
    double irecs;
    double vgsatqs;
    double vbdgs;
    double pbdgs;
    double betarecs;
    double kbdgates;
    double pgsrecd;
    double irecd;
    double vgsatqd;
    double vbdgd;
    double pbdgd;
    double betarecd;
    double kbdgated;
    double rth;
    double cth;
    int gmdisp;
    double taugmrf;
    int trapselect;
    double ctrap;
    double vttrap;
    double taut;
    double alphat1;
    double alphat2;
    double tempt;
    int noisemod;
    double shs;
    double shd;
    double kf;
    double af;
    double ffe;
    double minr;
    double minl;
    double minc;
    double LMIN;
    double WMIN;
    double LMAX;
    double WMAX;
    //  Variables of global_model scope
    // end verilog model variables=====
};

void registerDevice(const DeviceCountMap& deviceMap = DeviceCountMap(),
                    const std::set<int>& levelSet = std::set<int>());

} // namespace ADMSmvsg_cmc
} // namespace Device
} // namespace Xyce
#endif //Xyce_N_DEV_ADMSmvsg_cmc_h
